#pragma once
#include <fmtlog/fmtlog.h>
#include <Message.pb.h>
#include <google/protobuf/map.h>
#include <fmt/core.h>
#include <memory>
#include <mutex>
#include <unordered_map>
#include <string>
#include <Common/sqliteHelper.hpp>
#include <Common/FileHelper.hpp>
#include <filesystem>
#include <Common/Util.hpp>
namespace MY_MQ
{
    struct Exchange
    {
        using _self_ptr = std::shared_ptr<Exchange>;
        std::string _name;
        MQ_Protobuf::ExchangeType _type;
        bool _durable;
        bool _auto_delete;
        // 其他你需要的交换机参数
        // 用protobuf，方便协议
        google::protobuf::Map<std::string, std::string> _args;

        Exchange() {}
        Exchange(const std::string &name, MQ_Protobuf::ExchangeType type, bool durable, bool auto_delete, const google::protobuf::Map<std::string, std::string> &args = {})
        {
            Init(name, type, durable, auto_delete, args);
        }
        Exchange(const std::string &name, MQ_Protobuf::ExchangeType type, bool durable, bool auto_delete, const std::string & args = "")
        {
            Init(name, type, durable, auto_delete, args);
        }
        void Init(const std::string &exchange_name,
                  MQ_Protobuf::ExchangeType exchange_type,
                  bool durable,
                  bool auto_delete,
                  const google::protobuf::Map<std::string, std::string> &args)
        {
            _name = exchange_name;
            _type = exchange_type;
            _durable = durable;
            _auto_delete = auto_delete;
            for (const auto &[key, value] : args)
            {
                _args[key] = value;
            }
        };
        void Init(const std::string &exchange_name,
                  MQ_Protobuf::ExchangeType exchange_type,
                  bool durable,
                  bool auto_delete,
                  const std::string &args)
        {
            _name = exchange_name;
            _type = exchange_type;
            _durable = durable;
            _auto_delete = auto_delete;
            Serialization_Util::SetArgs(_args, args);
        }          
        void SetArgs(const std::string &Json_string_args)
        {
            Serialization_Util::SetArgs(_args, Json_string_args);
        }
        std::string serializeMap()
        {
           return Serialization_Util::serializeMap(_args);
        }
    };

    const std::string ExchangeSqlite_table_struct = "./config/ExchangeSqlite_table.string";

    // 负责把交换机里的数据给持久存储进sqlite数据库,
    class ExchangeDataManager
    {
        sqliteHelper _sqliteHelper;
        std::string _db_table;
    public:
        ExchangeDataManager(const std::string &db_path)
        {
            //检测路径目录是否存在，不存在创建目录
            if (!std::filesystem::exists(db_path))
            {
                std::filesystem::create_directories(std::filesystem::path(db_path).parent_path());
                loge("db_path not exist,已创建");
            }
            _sqliteHelper.open(db_path);
            _db_table = std::filesystem::path(ExchangeSqlite_table_struct).stem().string();
            createTable();
        }

        void createTable()
        {
            std::string create_table_sql;
            Filehelper(ExchangeSqlite_table_struct).read_as_string(create_table_sql);
            if (_sqliteHelper.exec(create_table_sql) == false)
            {
                loge("create table failed");
                abort();
            }
        }
        void removeTable()
        {
            if (_sqliteHelper.exec("DROP TABLE IF EXISTS " + _db_table) == false)
            {
                loge("remove table failed");
            }
            return;
        }
        // CREATE TABLE IF NOT EXISTS ExchangeSqlite_table{
        //     name varchar(32) primary key,
        //     type int not null,
        //     durable int not null,
        //     auto_delete int not null,
        //     arguments text
        // }
        // 根据表插入数据
        bool insert(Exchange::_self_ptr exchange_ptr)
        {
            std::string insert_sql = "INSERT INTO " + _db_table + " (name, type, durable, auto_delete, arguments)";
            insert_sql += " VALUES ('" + exchange_ptr->_name + "', " + std::to_string(exchange_ptr->_type) + ", " + std::to_string(exchange_ptr->_durable) + ", " + std::to_string(exchange_ptr->_auto_delete) + ", '" +  exchange_ptr->serializeMap() + "')";
            return _sqliteHelper.exec(insert_sql);
        }
        bool remove(Exchange::_self_ptr exchange_ptr)
        {
            std::string remove_sql = "DELETE FROM " + _db_table + " WHERE name = '" + exchange_ptr->_name + "'";
            return _sqliteHelper.exec(remove_sql) ;
        }
        std::unordered_map<std::string,Exchange::_self_ptr> recovery()
        {
            std::unordered_map<std::string,Exchange::_self_ptr> dataManager;
            std::string select_sql = "SELECT * FROM " + _db_table;
        
            if (_sqliteHelper.exec(select_sql, sql_callback, (void *)&dataManager) == false)
            {
                logw("select data failed,may be no table");
            }

            return dataManager;
        }

    private:
        static int sql_callback(void *data, int argc, char **argv, char **azColName)
        {
            // 读取数据库的内容，拿给dataManager
            std::unordered_map<std::string, Exchange::_self_ptr> *exchange_map = (std::unordered_map<std::string, Exchange::_self_ptr> *)data;
            Exchange::_self_ptr exchange_ptr = std::make_shared<Exchange>(argv[0], (MQ_Protobuf::ExchangeType)std::stoi(argv[1]), std::stoi(argv[2]), std::stoi(argv[3]), std::string(argv[4]?argv[4]:""));
            exchange_map->insert(std::make_pair(exchange_ptr->_name, exchange_ptr));
            return 0;
        }
    };

    //负责程序内调用，管理各个交换机生命周期的类
    class ExchangeManager{
        private:
        std::mutex _mutex;
        std::unordered_map<std::string, Exchange::_self_ptr> _exchange_map;
        ExchangeDataManager _exchangeDataManager;
        public:
        using self_ptr = std::shared_ptr<ExchangeManager>;
        ExchangeManager(std::string db_path):_exchangeDataManager(db_path){
            _exchange_map = _exchangeDataManager.recovery();
        }
        //声明交换机
        bool declareExchange(
            std::string name,
            MQ_Protobuf::ExchangeType type,
            bool durable = false,
            bool auto_delete = true,
            std::string arguments = ""
        )
        {
            std::lock_guard<std::mutex> lock(_mutex);
            if (_exchange_map.find(name) != _exchange_map.end())
            {
                logd("exchange already exist");
                return false;
            }
            Exchange::_self_ptr exchange_ptr = std::make_shared<Exchange>(name, type, durable, auto_delete, arguments);
            _exchange_map.insert(std::make_pair(name, exchange_ptr));
            return  _exchangeDataManager.insert(exchange_ptr);
        }
        //删除交换机
        bool removeExchange(const std::string &name)
        {
            std::lock_guard<std::mutex> lock(_mutex);
            if (_exchange_map.find(name) == _exchange_map.end())
            {
                logd("exchange not exist");
                return false;
            }
            auto it = _exchange_map.find(name);
            if(it->second->_durable==false)
            {
                _exchangeDataManager.remove(it->second);
            }
            _exchange_map.erase(name);
            return true;
        }
        bool exsits(const std::string &name)
        {
            std::lock_guard<std::mutex> lock(_mutex);
            return _exchange_map.find(name) != _exchange_map.end();
        }
        //当前交换机数量
        std::size_t size()
        {
            std::lock_guard<std::mutex> lock(_mutex);
            return _exchange_map.size();
        }
        Exchange::_self_ptr SelectExchange(const std::string &name)
        {
            std::lock_guard<std::mutex> lock(_mutex);
            return _exchange_map[name];
        }
        void clearTmpExchange()
        {
            std::lock_guard<std::mutex> lock(_mutex);
            while(_exchange_map.size())
            {
                auto it = _exchange_map.begin();
                if(it->second->_durable==false)
                {
                    _exchangeDataManager.remove(it->second);
                }
                _exchange_map.erase(it);
            }
        }
        //此举会清空即使持久化存储的交换机
        void clear()
        {
            std::lock_guard<std::mutex> lock(_mutex);
            _exchange_map.clear();
            _exchangeDataManager.removeTable();
        }
        ~ExchangeManager()
        {
            clearTmpExchange();
        }
    };
};